import asyncio
import tempfile
from pathlib import Path
from typing import Optional, Tuple
from datetime import datetime, timedelta

from md2ppt.parser.md_parser import MarkdownParser
from md2ppt.converter.ppt_builder import PPTBuilder

from .storage import StorageManager
from .validator import InputValidator
from api.models.request import ConversionOptions
from api.models.response import ConversionResult


class ConversionService:
    """转换服务"""
    
    def __init__(self, storage_manager: StorageManager):
        self.storage = storage_manager
    
    async def convert_content(
        self, 
        markdown_content: str, 
        options: ConversionOptions,
        output_filename: Optional[str] = None
    ) -> ConversionResult:
        """转换 Markdown 内容"""
        
        # 验证输入
        is_valid, error_msg = InputValidator.validate_markdown_content(markdown_content)
        if not is_valid:
            raise ValueError(error_msg)
        
        # 处理输出文件名
        if output_filename:
            output_filename = InputValidator.sanitize_filename(output_filename)
        else:
            output_filename = f"presentation_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pptx"
        
        # 在临时目录中执行转换
        with tempfile.TemporaryDirectory() as temp_dir:
            temp_path = Path(temp_dir)
            
            # 创建临时 Markdown 文件
            md_file = temp_path / "input.md"
            with open(md_file, 'w', encoding='utf-8') as f:
                f.write(markdown_content)
            
            # 执行转换
            output_file = await self._perform_conversion(
                md_file, 
                temp_path / output_filename,
                options
            )
            
            # 读取生成的文件
            with open(output_file, 'rb') as f:
                pptx_content = f.read()
            
            # 获取页面数量
            pages_count = await self._count_slides(output_file)
            
            # 存储文件
            file_id = await self.storage.store_file(
                pptx_content, 
                output_filename,
                "application/vnd.openxmlformats-officedocument.presentationml.presentation"
            )
            
            # 生成下载URL
            download_url = f"/api/v1/files/{file_id}"
            
            # 创建结果
            now = datetime.now()
            return ConversionResult(
                file_id=file_id,
                download_url=download_url,
                filename=output_filename,
                file_size=len(pptx_content),
                pages_count=pages_count,
                created_at=now,
                expires_at=now + timedelta(seconds=self.storage.ttl)
            )
    
    async def convert_file(
        self, 
        file_path: str, 
        options: ConversionOptions,
        output_filename: Optional[str] = None
    ) -> ConversionResult:
        """转换 Markdown 文件"""
        
        # 验证文件路径
        is_valid, error_msg = InputValidator.validate_file_path(file_path)
        if not is_valid:
            raise ValueError(error_msg)
        
        # 读取文件内容
        with open(file_path, 'r', encoding='utf-8') as f:
            markdown_content = f.read()
        
        # 如果没有指定输出文件名，使用输入文件名
        if not output_filename:
            input_path = Path(file_path)
            output_filename = input_path.stem + ".pptx"
        
        return await self.convert_content(markdown_content, options, output_filename)
    
    async def _perform_conversion(
        self, 
        input_file: Path, 
        output_file: Path, 
        options: ConversionOptions
    ) -> Path:
        """执行实际的转换过程"""
        
        # 使用现有的 md2ppt 转换逻辑
        parser = MarkdownParser()
        builder = PPTBuilder(theme_name=options.theme)
        
        # 解析 Markdown
        doc_structure = parser.parse_file(str(input_file))
        
        # 构建 PPT
        presentation = builder.build_from_structure(doc_structure)
        
        # 保存文件
        presentation.save(str(output_file))
        
        return output_file
    
    async def _count_slides(self, pptx_file: Path) -> int:
        """计算幻灯片数量"""
        try:
            from pptx import Presentation
            prs = Presentation(str(pptx_file))
            return len(prs.slides)
        except Exception:
            return 0
    
    async def get_file(self, file_id: str) -> Optional[Tuple[bytes, dict]]:
        """获取文件"""
        return await self.storage.get_file(file_id)
    
    async def cleanup_expired_files(self):
        """清理过期文件"""
        return await self.storage.cleanup_expired()